home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Mac / Contrib / PythonScript / getaete.py < prev    next >
Encoding:
Python Source  |  2000-06-23  |  9.6 KB  |  407 lines

  1. """
  2. Produces a 3 dictionaries from application aete's 
  3. to be read by PythonScript
  4.  
  5. v.02 january 31, 1998 added support for inheriting suites from aeut
  6. v.03 february 16, 1998 changes to identify
  7. v.04 february 26, 1998 simplified decode
  8. v.05 23/04/98 simplified _launch
  9.  
  10. """
  11. import baetools
  12. import macpath
  13. import sys
  14. import os
  15. import MacOS
  16. import StringIO
  17. import types
  18. from MACFS import *
  19. import macfs
  20. import string
  21. from Res import *
  22. import struct
  23.  
  24. # for testing only
  25. app ='CSOm' #'ezVu'# 'nwSP'#MACS'#
  26.  
  27. #Restrict the application suites to the dialect we want to use.
  28. LANG = 0 # 0 = English, 1 = French, 11 = Japanese
  29. lang = {0:'English', 1:'French', 11:'Japanese'}
  30.  
  31. #The following are neaded to open the application aete
  32. kASAppleScriptSuite    = 'ascr'
  33. kGetAETE            = 'gdte'
  34. attributes = {}
  35. arguments = {}
  36.  
  37. class AETE(baetools.TalkTo):
  38.     pass
  39.     
  40. def Getaete(app):
  41.     try:
  42.         data = openaete(app)
  43.     except MacOS.Error, msg:
  44.         if msg[0] == -609:
  45.             _launch(app)
  46.             data = openaete(app)
  47.     data = decode(data['----'].data)
  48.     data = compileaete(data)
  49.     return data
  50.     
  51.     
  52. def decode(data):
  53.     """Decode an aete into a python data structure"""
  54.     f = StringIO.StringIO(data)
  55.     aete = generic(getaete, f)
  56.     return aete
  57.  
  58. def simplify(item):
  59.     """Recursively replace singleton tuples by their constituent item"""
  60.     if type(item) is types.ListType:
  61.         return map(simplify, item)
  62.     elif type(item) == types.TupleType and len(item) == 2:
  63.         return simplify(item[1])
  64.     else:
  65.         return item
  66.  
  67.  
  68. ## Here follows the aete resource decoder.
  69. ## It is presented bottom-up instead of top-down because there are  direct
  70. ## references to the lower-level part-decoders from the high-level part-decoders.
  71. #
  72. def getflag(f, *args):
  73.     m = ''
  74.     c = f.read(2)
  75.     print `c`
  76.     if not c:
  77.         raise EOFError, 'in getflag' + str(args)
  78.     for n in c:
  79.         m = m + `ord(n)`
  80.  
  81. def getbyte(f, *args):
  82.     c = f.read(1)
  83.     if not c:
  84.         raise EOFError, 'in getbyte' + str(args)
  85.     return ord(c)
  86.  
  87. def getword(f, *args):
  88.     getalign(f)
  89.     s = f.read(2)
  90.     if len(s) < 2:
  91.         raise EOFError, 'in getword' + str(args)
  92.     return (ord(s[0])<<8) | ord(s[1])
  93.  
  94. def getlong(f, *args):
  95.     getalign(f)
  96.     s = f.read(4)
  97.     if len(s) < 4:
  98.         raise EOFError, 'in getlong' + str(args)
  99.     return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
  100.  
  101. def getostype(f, *args):
  102.     getalign(f)
  103.     s = f.read(4)
  104.     if len(s) < 4:
  105.         raise EOFError, 'in getostype' + str(args)
  106.     return s
  107.  
  108. def getpstr(f, *args):
  109.     c = f.read(1)
  110.     if len(c) < 1:
  111.         raise EOFError, 'in getpstr[1]' + str(args)
  112.     nbytes = ord(c)
  113.     if nbytes == 0: return ''
  114.     s = f.read(nbytes)
  115.     if len(s) < nbytes:
  116.         raise EOFError, 'in getpstr[2]' + str(args)
  117.     return s
  118.  
  119. def getalign(f):
  120.     if f.tell() & 1:
  121.         c = f.read(1)
  122.         ##if c <> '\0':
  123.         ##    print 'align:', `c`
  124.  
  125. def getlist(f, description, getitem):
  126.     count = getword(f)
  127.     list = []
  128.     for i in range(count):
  129.         list.append(generic(getitem, f))
  130.         getalign(f)
  131.     return list
  132.  
  133. def alt_generic(what, f, *args):
  134.     print "generic", `what`, args
  135.     res = vageneric(what, f, args)
  136.     print '->', `res`
  137.     return res
  138.  
  139. def generic(what, f, *args):
  140.     if type(what) == types.FunctionType:
  141.         return apply(what, (f,) + args)
  142.     if type(what) == types.ListType:
  143.         record = []
  144.         for thing in what:
  145.             item = apply(generic, thing[:1] + (f,) + thing[1:])
  146.             record.append(item)
  147.     return record
  148.     return "BAD GENERIC ARGS: %s" % `what`
  149.  
  150. getdata = [
  151.     (getostype, "type"),
  152.     (getpstr, "description"),
  153.     (getword, "flags")
  154.     ]
  155. getargument = [
  156.     (getpstr, "name"),
  157.     (getostype, "keyword"),
  158.     (getdata, "what")
  159.     ]
  160. getevent = [
  161.     (getpstr, "name"),
  162.     (getpstr, "description"),
  163.     (getostype, "suite code"),
  164.     (getostype, "event code"),
  165.     (getdata, "returns"),
  166.     (getdata, "accepts"),
  167.     (getlist, "optional arguments", getargument)
  168.     ]
  169. getproperty = [
  170.     (getpstr, "name"),
  171.     (getostype, "code"),
  172.     (getdata, "what")
  173.     ]
  174. getelement = [
  175.     (getostype, "type"),
  176.     (getlist, "keyform", getostype)
  177.     ]
  178. getclass = [
  179.     (getpstr, "name"),
  180.     (getostype, "class code"),
  181.     (getpstr, "description"),
  182.     (getlist, "properties", getproperty),
  183.     (getlist, "elements", getelement)
  184.     ]
  185. getcomparison = [
  186.     (getpstr, "operator name"),
  187.     (getostype, "operator ID"),
  188.     (getpstr, "operator comment"),
  189.     ]
  190. getenumerator = [
  191.     (getpstr, "enumerator name"),
  192.     (getostype, "enumerator ID"),
  193.     (getpstr, "enumerator comment")
  194.     ]
  195. getenumeration = [
  196.     (getostype, "enumeration ID"),
  197.     (getlist, "enumerator", getenumerator)
  198.     ]
  199. getsuite = [
  200.     (getpstr, "suite name"),
  201.     (getpstr, "suite description"),
  202.     (getostype, "suite ID"),
  203.     (getword, "suite level"),
  204.     (getword, "suite version"),
  205.     (getlist, "events", getevent),
  206.     (getlist, "classes", getclass),
  207.     (getlist, "comparisons", getcomparison),
  208.     (getlist, "enumerations", getenumeration)
  209.     ]
  210. getaete = [
  211.     (getbyte, "major version in BCD"),
  212.     (getbyte, "minor version in BCD"),
  213.     (getword, "language code"),
  214.     (getword, "script code"),
  215.     (getlist, "suites", getsuite)
  216.     ]
  217.  
  218. def compileaete(aete):
  219.     """Generate dictionary for a full aete resource."""
  220.     [major, minor, language, script, suites] = aete
  221.     suitedict = {}
  222.     gsuites = openaeut()
  223.     for gsuite in gsuites:
  224.         if gsuite[0] == 'AppleScript Suite':
  225.             suite = gsuite
  226.             suite = compilesuite(suite)
  227.             suitedict[identify(suite[0])] = suite[1:]
  228.     for suite in suites:
  229.         if language == LANG:
  230.             suitecode = suite[2]
  231.             if suite[5] == []:
  232.                 for gsuite in gsuites:
  233.                     if suitecode == gsuite[2]:
  234.                         suite = gsuite
  235.             suite = compilesuite(suite)
  236.             suitedict[identify(suite[0])] = suite[1:]
  237.     suitedict = combinesuite(suitedict)
  238.     return suitedict
  239.             
  240. def compilesuite(suite):
  241.     """Generate dictionary for a single suite"""
  242.     [name, desc, code, level, version, events, classes, comps, enums] = suite
  243.     eventdict ={}
  244.     classdict = {}
  245.     enumdict ={}
  246.     for event in events:
  247.         if event[6]:
  248.             for ev in event[6]:
  249.                 ev[0] = identify(ev[:2])
  250.         eventdict[identify(event[:2])] = event[1:]
  251.     for klass in classes:
  252.         if klass[3]:
  253.             for kl in klass[3]:
  254.                 kl[0] = identify(kl[:2])
  255.         classdict[identify(klass[:2])] = klass[1:]
  256.     for enum in enums:
  257.         enumdict[enum[0]] = enum[1]
  258.     return name, eventdict, classdict, enumdict
  259.         
  260. def combinesuite(suite):
  261.     """Combines suite dictionaries to seperate event, class, enumeration dictionaries
  262.     """
  263.     
  264.     suitelist = []
  265.     eventDict ={}
  266.     classDict ={}
  267.     enumDict ={}
  268.     for value in suite.values():
  269.         for key in value[0].keys():
  270.             val = value[0][key]
  271.             eventDict[key] = val
  272.         for key in value[1].keys():
  273.             val = value[1][key]
  274.             if key in classDict.keys():
  275.                 nval = classDict[key][2]
  276.                 val[2] = val[2] + nval
  277.             classDict[key] = val
  278.         for key in value[2].keys():
  279.             val = value[2][key]
  280.             enumDict[key] = val
  281.     return     eventDict, classDict, enumDict
  282.         
  283.  
  284. illegal_ids = [ "for", "in", "from", "and", "or", "not", "print", "class", "return",
  285.     "def", "name", 'data' ]
  286.  
  287. def identify(str):
  288.     """Turn any string into an identifier:
  289.     - replace space by _
  290.     - remove ',' and '-'
  291.     capitalise
  292.     """
  293.     if not str[0]:
  294.         if str[1] == 'c@#!':
  295.             return "Every"
  296.         else:
  297.             return 'Any'
  298.     rv = string.replace(str[0], ' ', '_')
  299.     rv = string.replace(rv, '-', '')
  300.     rv = string.replace(rv, ',', '')
  301.     rv = string.capitalize(rv)
  302.     return rv
  303.  
  304.  
  305. def openaete(app):
  306.     """open and read the aete of the target application"""
  307.     arguments['----'] = LANG
  308.     _aete = AETE(app)
  309.     _reply, _arguments, _attributes = _aete.send(kASAppleScriptSuite, kGetAETE, arguments, attributes)
  310.     if _arguments.has_key('errn'):
  311.         raise baetools.Error, baetools.decodeerror(_arguments)
  312.     return  _arguments
  313.  
  314. def openaeut():
  315.     """Open and read a aeut file.
  316.     XXXXX This has been temporarily hard coded until a Python aeut is written XXXX"""
  317.  
  318.     fullname = dialect
  319.     rf = OpenRFPerm(fullname, 0, 1)
  320.     try:
  321.         UseResFile(rf)
  322.         resources = []
  323.         for i in range(Count1Resources('aeut')):
  324.             res = Get1IndResource('aeut', 1+i)
  325.             resources.append(res)
  326.         for res in resources:
  327.             data = res.data
  328.             data = decode(data)[4]
  329.     finally:
  330.         CloseResFile(rf)
  331.     return data
  332.     
  333. def dialect():
  334.     """find the correct Dialect file"""
  335.  
  336.     dialect = lang[LANG] + " Dialect"
  337.     try:
  338.         ##System 8
  339.         vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kScriptingAdditionsFolderType, 0)
  340.         fss = macfs.FSSpec((vRefNum, dirID, ''))
  341.         fss = fss.as_pathname()
  342.     except macfs.error:
  343.         ##Sytem 7
  344.         vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kExtensionFolderType, 0)
  345.         fss = macfs.FSSpec((vRefNum, dirID, ''))
  346.         fss = fss.as_pathname()
  347.         fss = macpath.join(fss, "Scripting Additions")
  348.     fss = macpath.join(fss, "Dialect")
  349.     fss = macpath.join(fss, dialect)
  350.     return fss
  351.     
  352.     
  353. #def openosax():
  354. #    """Open and read the aetes of osaxen in the scripting additions folder"""
  355. #
  356. #    # System 7.x
  357. #    aete = []
  358. #    vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kExtensionFolderType, 0)
  359. #    fss = macfs.FSSpec((vRefNum, dirID, ''))
  360. #    fss = fss.as_pathname()
  361. #    osax = macpath.join(fss, "Scripting Additions")
  362. #    for file in os.listdir(osax):
  363. #        fullname = macpath.join(osax, file)
  364. #        print fullname
  365. #        rf = OpenRFPerm(fullname, 0, 1)
  366. #        try:
  367. #            UseResFile(rf)
  368. #            resources = []
  369. #            for i in range(Count1Resources('aete')):
  370. #                res = Get1IndResource('aete', 1+i)
  371. #                resources.append(res)
  372. #            for res in resources:
  373. #                data = res.data
  374. #                data = decode(data)[4]
  375. #        finally:
  376. #            CloseResFile(rf)
  377. #        aete.append(data)
  378. #    print data
  379.  
  380.  
  381. #The following should be replaced by direct access to a python 'aeut'
  382.  
  383. def _launch(appfile):
  384.     """Open a file thru the finder. Specify file by name or fsspec"""
  385.  
  386. #    from PythonScript import PyScript
  387.     import baetypes
  388.     _finder = AETE('MACS')
  389.     parameters ={}
  390.     parameters['----'] = eval("baetypes.ObjectSpecifier('%s', '%s', %s)" % ('appf', 'ID  ', `appfile`))
  391.     _reply, _arguments, _attributes = _finder.send( 'aevt', 'odoc', parameters , attributes = {})
  392.     if _arguments.has_key('errn'):
  393.         raise baetools.Error, baetools.decodeerror(_arguments)
  394.     # XXXX Optionally decode result
  395.     if _arguments.has_key('----'):
  396.         return _arguments['----']
  397.  
  398.  
  399.  
  400. if __name__ == '__main__':
  401. #    import profile
  402. #    profile.run('Getaete(app)', 'Getaeteprof')
  403.     Getaete(app)
  404. #    openosax()
  405. #    openaete('ascr')
  406. #    sys.exit(1)
  407.